#include <PDFScan.h>

struct PdfVersion
{
	unsigned char user[4];   //pdf Singal
	char version[4];		 //PDF Version
};


cPDFScan::cPDFScan(char* FileBuff, long FileSize)
{
	jsnum = 0;
}

cPDFScan::cPDFScan(char* FilePath)
{
	jsnum = 0;
}

cPDFScan::cPDFScan()
{
	jsnum = 0;
}

cPDFScan::~cPDFScan()
{
	jsnum = 0;
}

cPDFScan::IsMalware()
{
	return bMalware;
}

BOOL cPDFScan::ScanObj();
{
	// Some important structure flags
	int stream=0,endstream=0,streamlength=0;
	int openaction=0,javascript=0,jspos=0;
	int obj=0,endobj=0,objlength=0;
	int xref=0,startxref=0,objinxref=0;
	int richmedia=0;
	int Launch=0;
	int JBIG2Decode=0;
	int FlateDecode=0;
	int Page=0;
	int AcroForm=0;
	int trailer=0;
	int Encrypt=0;
	int ObjStm=0;

	//Get PDF Signal
	PdfVersion* pVersion =(PdfVersion *)cFileBuff;
	if(strncmp((char *)pVersion->user,"%PDF",4)!=0)
	{
		return FALSE;
	}

	//Scan Object Signals
	for(int i=0;i<FileSize;i++)
	{
		// stream
		if(IsWord(i, "stream"))
		{
			stream=stream+1;
		}
		
		// endstream
		if(IsWord(i, "endstream"))
		{
			endstream=endstream+1;
		}
		
		// OpenAction
		if(IsWord(i, "OpenAction"))
		{
			openaction=openaction+1;
		}

		// JavaScript
		if(IsWord(i, "JavaScript"))
		{
			javascript=javascript+1;
			if(jsnum < 10)
			{
				JSpos[jsnum] = i;
				jsnum++;
			}
		}

		// obj.
		if(IsWord(i," obj"))
		{
			obj=obj+1;
		}

		// endobj.
		if(IsWord(i, "endobj"))
		{
			endobj=endobj+1;
		}

		// startxref
		if (
			(cFileBuff[i]  ==0x73) && (cFileBuff[i+1]==0x74) &&
			(cFileBuff[i+2]==0x61) && (cFileBuff[i+3]==0x72) &&
			(cFileBuff[i+4]==0x74) && (cFileBuff[i+5]==0x78) &&
			(cFileBuff[i+6]==0x72) && (cFileBuff[i+7]==0x65) && 
			(cFileBuff[i+8]==0x66)
			)
		{
			startxref=startxref+1;
			
		}

		// xref.
		if (
			(cFileBuff[i]  ==0x0A)&& (cFileBuff[i+1]==0x78) &&
			(cFileBuff[i+2]==0x72) && (cFileBuff[i+3]==0x65) && 
			(cFileBuff[i+4]==0x66) && (cFileBuff[i+5]==0x0A)
			)
		{
			xref=xref+1;
		}

		// 查找 n.的位置objinxref
		// 计算在交叉表中的每个对像
		if (
			(cFileBuff[i]  ==0x20) && (cFileBuff[i+1]==0x6E) && 
			((cFileBuff[i+2]==0x0D) || (cFileBuff[i+2]==0x20))
			)
		{
			objinxref=objinxref+1;
		}

		// RichMedia
		if (IsWord(i, "RichMedia"))
		{
			richmedia=richmedia+1;
		}

		// Launch
		if (IsWord(i, "Launch"))
		{
			Launch=Launch+1;
		}

		// JBIG2Decode
		if (IsWord(i, "JBIG2Decode"))
		{
			JBIG2Decode=JBIG2Decode+1;
		}

		// JS
		if (IsWord(i, "/JS "))
		{
			jspos=jspos+1;
		}

		// AcroForm
		if (
			(cFileBuff[i]  ==0x41) && (cFileBuff[i+1]==0x63) &&
			(cFileBuff[i+2]==0x72) && (cFileBuff[i+3]==0x6F) && 
			(cFileBuff[i+4]==0x46) && (cFileBuff[i+5]==0x6F) &&
			(cFileBuff[i+6]==0x72) && (cFileBuff[i+7]==0x6D) 
			)
		{
			AcroForm=AcroForm+1;
		}

		// ObjStm
		if (
			(cFileBuff[i]  ==0x4F) && (cFileBuff[i+1]==0x62) &&
			(cFileBuff[i+2]==0x6A) && (cFileBuff[i+3]==0x53) && 
			(cFileBuff[i+4]==0x74) && (cFileBuff[i+5]==0x6D) 
			)
		{
			ObjStm=ObjStm+1;
		}

		// Encrypt
		if (
			(cFileBuff[i]  ==0x45) && (cFileBuff[i+1]==0x6E) &&
			(cFileBuff[i+2]==0x63) && (cFileBuff[i+3]==0x72) && 
			(cFileBuff[i+4]==0x79) && (cFileBuff[i+5]==0x70) && 
			(cFileBuff[i+6]==0x74)   
			)
		{
			Encrypt=Encrypt+1;
		}

		// Page
		if (
			(cFileBuff[i]  ==0x50) && (cFileBuff[i+1]==0x61) &&
			(cFileBuff[i+2]==0x67) && (cFileBuff[i+3]==0x65) 
			)
		{
			Page=Page+1;
		}

		// [/FlateDecode]
		if (
			(cFileBuff[i]  ==0x5B) && (cFileBuff[i+1]==0x2F) &&
			(cFileBuff[i+2]==0x46) && (cFileBuff[i+3]==0x6C) && 
			(cFileBuff[i+4]==0x61) && (cFileBuff[i+5]==0x74) &&
			(cFileBuff[i+6]==0x65) && (cFileBuff[i+7]==0x64) &&
			(cFileBuff[i+8]==0x6F) 
			)
		{
			FlateDecode=FlateDecode+1;
		}


		// Some Scan Rules
		if (FileSize <= 1024*1024)
		{
			// Page Details
			if (Page <= 3)
			{
				// must be the same
				if(endobj!=obj)
				{
					return TRUE;
				}
				// xref modify
				else if (endobj>objinxref||objinxref==0)
				{
					return TRUE;
				}
				// OpanAction
				else if(openaction != 0){
					// have JS in file?
					if(javascript != 0 || jspos != 0)
					{
						if(jsnum > 0)
						{
							scanObj();
						}
					}else{
						// any swf & other file in it?
						if(richmedia != 0)
						{
							return TRUE;
						}
					}
				}
			}
		}
		return FALSE;
}

BOOL cPDFScan::IsWord(int pos, char* keyWord)
{
	int keyLen = strlen(keyWord);
	int tempint;
	int j = 0;
	for (tempint = pos; tempint < pos+keyLen; tempint++)
	{
		if(!IsChar(cFileBuff[tempint], keyWord[j]))
		{
			return FALSE;
		}
	}
	return TRUE;
}

BOOL cPDFScan::IsChar(char* tempbuff, char keyChar)
{
	if (tempbuff[0] == 0x35)
	{
		char tempchar[2];
		tempchar[0] = tempbuff[1];
		tempchar[1] = tempbuff[2];
		char temp = atoi(tempchar);
		if(temp == keyChar)
		{
			return TRUE;
		}else{
			return FALSE;
		}
	}else{
		if(tempbuff[0] == keyChar)
		{
			return TRUE;
		}else{
			return FALSE;
		}
	}
	return FALSE;
}

BOOL cPDFScan::DoPDFScan()
{
	if(scanObj())
	{
		bMalware = TRUE;
	}else{
		bMalware = FALSE;
	}
}